package com.sinotn.ks.node.sign.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Date;
import java.util.UUID;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

import com.sinotn.SinotnLogger;
import com.sinotn.SinotnRuntime;
import com.sinotn.component.KsFace;
import com.sinotn.error.MessageException;
import com.sinotn.ks.definition.Examinee;
import com.sinotn.ks.node.runtime.FileStoreUtil;
import com.sinotn.ks.node.runtime.service.InvigilatorService;
import com.sinotn.ks.node.runtime.vo.ExamCertifierVO;
import com.sinotn.ks.node.sign.service.FaceService;
import com.sinotn.util.FileUtil;

public class DefaultFaceService implements FaceService,InitializingBean {
	@Autowired
	private KsFace ksFace;
	@Autowired
	private InvigilatorService invigilatorService;
	private int threshold=450;

	private void formatFaceCount(int faceCount, String photoName){
		if(faceCount>0){
			return;
		}
		if(faceCount==0){
			throw new MessageException((photoName==null?"":photoName) + "照片不合格，未识别到人脸");
		}
		throw new MessageException("人脸数识别服务不可用("+faceCount+")");
	}

	@Override
	public int similarCertify(Examinee examinee, String ipAddr, String mac, String srcPhotoText, String validPotoText, String certifierName) {
		this.invigilatorService.certifyValid(examinee);
		File destphoto=null;
		try{
			// 原照片数据(报名照片、身份证照片)
			byte[] buffer1=null;
			if (StringUtils.isEmpty(srcPhotoText)){
				File folder=FileStoreUtil.getPhotoFolder(examinee.getRoomId(), false);
				if (folder==null || folder.exists()){
					File signFile=new File(folder, FileStoreUtil.getPhotoName(examinee.getId()));
					if(signFile.exists()){
						buffer1=new byte[5*1024];
						int faceCount=this.ksFace.faceconvert(signFile, buffer1);
						this.formatFaceCount(faceCount, "报名");
					}
				}
			}else{
				File folder=FileStoreUtil.getPhotoFolder(examinee.getRoomId(), true);
				File file=new File(folder, "src.jpg");
				FileStoreUtil.writeBase64Photo(srcPhotoText, file);
				buffer1=new byte[5*1024];
				int faceCount=this.ksFace.faceconvert(file, buffer1);
				this.formatFaceCount(faceCount, "原");
			}
			if(buffer1==null){
				throw new MessageException("考生报名照片不存在");
			}

			// 比对照片
			destphoto = new File(SinotnRuntime.getTempFolder(), UUID.randomUUID().toString()+".jpg");
			FileStoreUtil.writeBase64Photo(validPotoText, destphoto);
			byte[] buffer2=new byte[5*1024];
			int faceCount=this.ksFace.faceconvert(destphoto, buffer2);
			this.formatFaceCount(faceCount, "拍摄");
			int similarValue=this.ksFace.facecompare(buffer1, buffer2);
			if(similarValue < 0){
				throw new MessageException("人脸比对服务不可用("+similarValue+")");
			}
			if (similarValue >= this.threshold){
				//保存照片(http rs/examinee/${roomId})
				File folder=FileStoreUtil.getPhotoHttpFolder(examinee.getRoomId(), true);
				final File file=new File(folder, FileStoreUtil.getPhotoName(examinee.getId()));
				FileUtil.copyFile(destphoto, file);//覆盖显示照片
				//冗余保存业务照片
				folder=FileStoreUtil.getStoreFolder(examinee.getRoomId(), examinee.getId(), true);
				File dest=new File(folder, "last.jpg");
				if(dest.exists()){
					dest.renameTo(new File(folder, System.currentTimeMillis()+".jpg"));
					dest=new File(folder, "last.jpg");
				}
				FileUtil.copyFile(destphoto, dest);
				examinee.updatePhotoInfo();

				byte certify=2;//人脸比对校验状态为2
				ExamCertifierVO certifierVo=new ExamCertifierVO();
				certifierVo.setCertifyText(examinee.getId()+":"+similarValue+"|"+this.threshold);
				certifierVo.setCertifyTime(new Date());
				certifierVo.setCertifyType(certify);
				certifierVo.setExamInfoId(examinee.getExamItemId());
				certifierVo.setIpAddr(ipAddr);
				certifierVo.setMac(mac);
				certifierVo.setTeacherName(certifierName);

				this.invigilatorService.doCertify(examinee, certifierVo, file);
			} else {
				similarValue= (-similarValue);
			}
			return similarValue;
		}finally{
			if(destphoto!=null && destphoto.exists()){
				destphoto.delete();
			}
		}
	}

	@Override
	public int getThreshold() {
		return this.threshold;
	}

	@Override
	public void setThreshold(int threshold) {
		if(threshold>0 && threshold<=999){
			this.threshold=threshold;
			File file=new File(SinotnRuntime.getBinFolder(), "similar.dt");
			PrintWriter pw=null;
			try{
				pw=new PrintWriter(file, "utf-8");
				pw.print(String.valueOf(threshold));
			}catch(Throwable e){
				SinotnLogger.DEBUG.error("加载人脸比对配置数据发生系统错误", e);
			}finally{
				IOUtils.closeQuietly(pw);
			}
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		File file=new File(SinotnRuntime.getBinFolder(), "similar.dt");
		if(file.exists()){
			BufferedReader br=null;
			try{
				br=new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
				String line=br.readLine();
				if(StringUtils.isNotEmpty(line)){
					this.threshold=Integer.valueOf(line);
				}
			}catch(Throwable e){
				SinotnLogger.DEBUG.error("加载人脸比对配置数据发生系统错误", e);
			}finally{
				IOUtils.closeQuietly(br);
			}
		}
	}
}
